package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

//①使用bytes.NewReader/bytes.Buffer来存储要解码的ascii串
//②使用binary.Read来解码
func DecodeExample() {
	fmt.Println("\n Example of Decode ---")
	//var pi float64
	var pi int64
	//bpi := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
	bpi := []byte("Hello,ssssdf")
	fmt.Println("bpi:", string(bpi))
	buf := bytes.NewReader(bpi)
	err := binary.Read(buf, binary.LittleEndian, &pi)
	// 这里可以继续读出来存在变量里, 这样就可以解码出来很多, 读的次序和变量类型要对
	// binary.Read(buf, binary.LittlEndian, &v2)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Print(pi)
	// 3.141592653589793
}

//①使用bytes.Buffer来存储编码生成的串
//②使用binary.Write来编码存储在①的buf中
func EncodeExample() {
	fmt.Println("\n Example of Encode ---")
	//	var pi float64 = 3.141592653589793
	buf := new(bytes.Buffer)
	//	err := binary.Write(buf, binary.LittleEndian, pi)
	// 这里可以继续往buf里写, 都存在buf里
	err := binary.Write(buf, binary.LittleEndian, uint16(1028))
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Print(buf.Bytes())
	// [24 45 68 84 251 33 9 64]
}
func EncodeDecoder() {
	fmt.Println("\n Example of EncodeDecoder ---")
	var pi float64 = 3.141592653589793
	buf := new(bytes.Buffer)
	// func Write(w io.Writer, order ByteOrder, data interface{}) error
	// 将data的binary编码格式写入w，data必须是定长值、定长值的切片、定长值的指针。order指定写入数据的字节序，写入结构体时，名字中有'_'的字段会置为0
	err := binary.Write(buf, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Println("Encode:", buf.Bytes()) //  Encode: [24 45 68 84 251 33 9 64]

	var po float64
	bufo := bytes.NewReader(buf.Bytes())
	// func Read(r io.Reader, order ByteOrder, data interface{}) error
	// 从r中读取binary编码的数据并赋给data，data必须是一个指向定长值的指针或者定长值的切片。从r读取的字节使用order指定的字节序解码并写入data的字段里当写入结构体是，名字中有'_'的字段会被跳过，这些字段可用于填充（内存空间）。
	err = binary.Read(bufo, binary.LittleEndian, &po)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Println("Decode:", po) // Decode: 3.141592653589793
}

func DecodeEncoder() {
	fmt.Println("\n Example of DecodeEncoder ---")
	var po int32
	//bpi := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
	bpi := []byte("hello,wd")
	bufo := bytes.NewReader(bpi)
	// func Read(r io.Reader, order ByteOrder, data interface{}) error
	// 从r中读取binary编码的数据并赋给data，data必须是一个指向定长值的指针或者定长值的切片。从r读取的字节使用order指定的字节序解码并写入data的字段里当写入结构体是，名字中有'_'的字段会被跳过，这些字段可用于填充（内存空间）。
	err := binary.Read(bufo, binary.LittleEndian, &po)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Println("Decode:", po) // Decode: 3.141592653589793

	//var pi float64 = 3.141592653589793
	buf := new(bytes.Buffer)
	// func Write(w io.Writer, order ByteOrder, data interface{}) error
	// 将data的binary编码格式写入w，data必须是定长值、定长值的切片、定长值的指针。order指定写入数据的字节序，写入结构体时，名字中有'_'的字段会置为0
	err = binary.Write(buf, binary.LittleEndian, po)
	if err != nil {
		fmt.Println("binary.Read failed:", err)
	}
	fmt.Println("Encode:", string(buf.Bytes())) //  Encode: [24 45 68 84 251 33 9 64]
}

//  func Varint(buf []byte) (int64, int)
//  从buf解码一个int64，返回该数字和读取的字节长度，如果发生了错误，该数字为0而读取长度n返回值的意思是：
//	n == 0: buf不完整，太短了
//	n  < 0: 值太大了，64比特装不下（溢出），-n为读取的字节数
func VarintExample() {
	fmt.Println("\n Example of Varint ---")
	b := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}
	fmt.Println("b:", b)
	d, n := binary.Varint(b)
	if d == 0 {
		if n == 0 {
			fmt.Println("buf is too short")
		} else if n < 0 {
			fmt.Println("buf is too larger")
		}
	}
	fmt.Println("d:", d)
	fmt.Println("n:", n)
}
func main() {
	y := [20]byte{0x01}
	fmt.Println("len(y):", len(y))
	//VarintExample()
	//EncodeExample()
	//DecodeExample()
	EncodeDecoder()
	DecodeEncoder()
}
